package com.moyuduo.java8.stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

/**
*@author litao,School of computer and software engineering,Xihua University
*@date 2020年3月26日
*/
public class StreamTest {

	/**
	 * 创建Stream的几种方式
	 */
	@Test
	public void test1() {
		//1通过Collection提供的stream()和parallelStream()方法
		List<String> list = Arrays.asList("a","b","c");
		Stream<String> stream1 = list.stream();
		Stream<String> stream2 = list.parallelStream();
		
		//2通过Arrays的静态方法stream()
		String[] strs= {"a","b","c"};
		Stream<String> stream3 = Arrays.stream(strs);
		
		//3通过Stream类中的静态方法of()
		Stream<String> stream4 = Stream.of("a","b","c");
		
		//4通过Stream类的iterate方法生成无限流
		Stream<Integer> stream5 = Stream.iterate(0, (x)->x+1);
		
		//5通过Stream的generate方法生成无限流
		Stream.generate(()->Math.random());
		
	}
	//中间操作
	/**
	 * 过滤
	 */
	@Test
	public void test2() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Stream<Integer> stream = list.stream();
		stream = stream.filter(
				(x)->{
			System.out.println(x);
			return x.compareTo(2)>0;}
			);
		
		//stream.forEach(System.out::println);
	}
	
	/**
	 * 截断流
	 */
	@Test
	public void test3() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Stream<Integer> stream = list.stream();
		stream=stream.limit(3);
		stream.forEach(System.out::println);
	}
	
	/**
	 * 跳过指定个元素
	 */
	@Test
	public void test4() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Stream<Integer> stream = list.stream();
		stream=stream.skip(2);
		stream.forEach(System.out::println);
	}
	
	/**
	 * 唯一筛选
	 */
	@Test
	public void test5() {
		List<Integer> list = Arrays.asList(1,2,3,4,5,5);
		Stream<Integer> stream = list.stream();
		stream.distinct().forEach(System.out::println);
	}
	
	/**
	 * 映射
	 */
	@Test
	public void test6() {
		List<String> list = Arrays.asList("a","b","c");
		Stream<String> stream = list.stream();
		stream=stream.map((x)->x.toUpperCase());
		stream.forEach(System.out::println);
	}
	
	public static Stream<Character> toStream(String s){
		List<Character> list=new ArrayList<Character>();
		char[] chs = s.toCharArray();
		for (char c : chs) {
			list.add(c);
		}
		Stream<Character> stream = list.stream();
		return stream;
	}
	
	@Test
	public void test7() {
		List<String> list = Arrays.asList("aaa","bbb","ccc");
		Stream<Stream<Character>> stream = list.stream().map(StreamTest::toStream);
		stream.forEach((s)->s.forEach(System.out::println));
	}
	
	@Test
	public void test8() {
		List<String> list = Arrays.asList("aaa","bbb","ccc");
		list.stream().flatMap(StreamTest::toStream).forEach(System.out::println);
	}
	
	//终止操作
	/**
	 * 匹配所有元素
	 */
	@Test
	public void test9() {
		List<String> list = Arrays.asList("aaa","bbb","ccc");
		boolean allMatch = list.stream().allMatch((s)->s.length()>2);
		System.out.println(allMatch);
	}
	
	/**
	 * 任一匹配
	 */
	@Test
	public void test10() {
		List<String> list = Arrays.asList("aaa","bbb","ccc");
		boolean anyMatch = list.stream().anyMatch((s)->s.equals("bbb"));
		System.out.println(anyMatch);
	}
	
	/**
	 * 所有不匹配
	 */
	@Test
	public void test11() {
		List<String> list = Arrays.asList("aaa","bbb","ccc");
		boolean noneMatch = list.stream().noneMatch((s)->s.equals("ddd"));
		System.out.println(noneMatch);
	}
	
	/**
	 * 第一个元素
	 */
	@Test
	public void test12() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Optional<Integer> findFirst = list.stream().findFirst();
		System.out.println(findFirst.get());
	}
	
	/**
	 * 任一一个元素 
	 */
	@Test
	public void test13() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Optional<Integer> findAny = list.parallelStream().findAny();
		System.out.println(findAny.get());
	}
	
	/**
	 * 流中元素的个数
	 */
	@Test
	public void test14() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		long count = list.stream().count();
		System.out.println(count);
	}
	
	/**
	 * 流中元素的最大值
	 */
	@Test
	public void test15() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Optional<Integer> max = list.stream().max(Integer::compare);
		System.out.println(max.get());
	}
	
	/**
	 * 流中元素的最小值
	 */
	@Test
	public void test16() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Optional<Integer> min = list.stream().min(Integer::compare);
		System.out.println(min.get());
	}
	
	/**
	 * 规约，将流中的元素反复结合得到一个最终值
	 */
	@Test
	public void test17() {
		List<Integer> list = Arrays.asList(1,2,3,4,5);
		Optional<Integer> reduce = list.stream().reduce(Integer::sum);
		System.out.println(reduce.get());
		
		Integer reduce2 = list.stream().reduce(0, (x,y)->{
			System.out.println(x+"->"+y);
			return x+y;
		});
		System.out.println(reduce2);
	}
	
	/**
	 * 收集，将流转换成其他形式
	 */
	@Test
	public void test18() {
		List<Integer> list = Arrays.asList(1,2,3,4,5,5);
		Set<Integer> collect = list.stream().collect(Collectors.toSet());
		System.out.println(collect);
	}
	
	@Test
	public void test19() {
		List<Integer> list = Arrays.asList(1,2,3,4,5,5);
		Optional<Integer> collect = list.stream().collect(Collectors.maxBy(Integer::compareTo));
		System.out.println(collect.get());
	}
	
	@Test
	public void test20() {
		List<Stu> list = Arrays.asList(
				new Stu("张三",20,"男"),
				new Stu("李四",22,"女"),
				new Stu("王五",18,"男"),
				new Stu("赵六",20,"女"),
				new Stu("田七",22,"女")
				);
		Map<String, List<Stu>> collect = list.stream().collect(Collectors.groupingBy(Stu::getGender));
		System.out.println(collect);
	}
	
	@Test
	public void test21() {
		List<Stu> list = Arrays.asList(
				new Stu("张三",20,"男"),
				new Stu("李四",22,"女"),
				new Stu("王五",18,"男"),
				new Stu("赵六",20,"女"),
				new Stu("田七",22,"女")
				);
		Map<Integer, Map<String, List<Stu>>> collect = list.stream()
				.collect(Collectors.groupingBy(Stu::getAge, Collectors.groupingBy(Stu::getGender)));
		System.out.println(collect);
	}
	
	
	@Test
	public void test22() {
		List<Stu> list = Arrays.asList(
				new Stu("张三",20,"男"),
				new Stu("李四",22,"女"),
				new Stu("王五",18,"男"),
				new Stu("赵六",20,"女"),
				new Stu("田七",22,"女")
				);
		Map<Boolean, List<Stu>> collect = list.stream()
				.collect(Collectors.partitioningBy((e)->((Stu)e).getAge()>20));
		System.out.println(collect);
	}
}

class Stu{
	String name;
	Integer age;
	String gender;
	public Stu(String name, Integer age, String gender) {
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	@Override
	public String toString() {
		return "Stu [name=" + name + ", age=" + age + ", gender=" + gender + "]";
	}
	
	
}
